#| label: load_librarieslibrary(readr)library(readxl)library(pxmake) # to load PX fileslibrary(pxR) # to load PX fileslibrary(jsonlite) # to load JSON fileslibrary(purrr)library(writexl) # Write Excel fileslibrary(dplyr)library(tidyverse)library(ggplot2) # Diagramslibrary(ggforce) # Diagramslibrary(DT) # datatable()library(DescTools)
2 Functions
Code anzeigen
#| label: load_functions### ########################################################## Duplikate in df finden & als $unique oder $duplicates selektionierbar machenfind_and_remove_duplicates <-function(df) {list(unique = df[!duplicated(df), ],duplicates = df[duplicated(df) |duplicated(df, fromLast =TRUE), ] )}### ########################################################## Aktive National- & Ständeräte identifizieren und selektionierbar machenfilter_active <-function(data, von, bis) { von <-as.Date(von) bis <-as.Date(bis) data %>%filter( DateJoining <= bis, # Eintritt vor oder am Ende des Zeitraumsis.na(DateLeaving) | DateLeaving >= von # Kein Austritt oder Austritt nach Beginn des Zeitraums )}### ########################################################## Duplikate in df finden & als $unique oder $duplicates selektionierbar machen
3ETL: Extract, Transform, Load
Daten werden aus verschiedenen Excel-Dateien ausgelesen, unabhängig davon, wie komplex oder verschachtelt sie sind (z. B. mehrere Sheets, verbundene Zellen, unterteilte Datenblöcke).
Bei Excel-Dateien mit mehreren Sheets werden Functions angewendet.
Header werden identifiziert und ggf. aus mehreren Zeilen zusammengesetzt.
Daten werden bereinigt, normalisiert und in das gewünschte Zielformat gebracht (z. B. Wide zu Long, Entfernen von Leerzeilen, Auflösen von verbundenen Zellen, Vereinheitlichung der Spaltenstruktur).
Die transformierten Daten werden für die weitere Analyse und Visualisation zu Verfügung gestellt.
3.1 Lookup tables
3.1.1 Parteinamen
Die verschiedenen Quellen verwenden teils unteschiedliche Parteibezeichnungen. Zur Vereinheitlichung wird deshalb initial eine Lookup Tabelle gebildet.
Code anzeigen
#| label: load_parties# Dataframe bilden aus zwei Vektorenparteinamen <-data.frame(kuerzel =c("fdp", "sps", "svp", "mitte", "evp", "gps", "glp", "ucsp", "pda", "sd", "edu", "fps", "lega", "kvp", "mcg", "cvp", "bdp", "lps", "ldu", "poch", "rep", "eco", "sgv", "sbv", "sgb", "travs", "sav", "vsa", "vpod", "voev", "tcs", "vcs", "acs", "sbk", "ssv", "gem", "kdk", "kkjpd", "gdk", "ldk"),name =c("Freisinnig-demokratische Partei (FDP.Die Liberalen)", "Sozialdemokratische Partei", "Schweizerische Volkspartei (bis 1936 Parolen der BGB Bern)", "Die Mitte", "Evangelische Volkspartei", "Grüne Partei der Schweiz", "Grünliberale Partei", "Christlichsoziale Partei der Schweiz (von der CVP unabhängige CSP)", "Partei der Arbeit", "Schweizer Demokraten", "Eidgenössisch-Demokratische Union", "Autopartei", "Lega dei Ticinesi", "Katholische Volkspartei", "Mouvement Citoyens Genevois", "Christlichdemokratische Volkspartei", "Bürgerlich-Demokratische Partei", "Liberale Partei der Schweiz", "Landesring der Unabhängigen", "Progressive Organisationen der Schweiz", "Schweizerische Republikanische Bewegung", "Economiesuisse (bis 15.9.2000: Schweizerischer Handels- und Industrieverein SHIV (Vorort))", "Schweizerischer Gewerbeverband", "Schweizer Bauernverband", "Schweizerischer Gewerkschaftsbund", "Travail.Suisse (bis 2002: Parolen des Christlichnationalen Gewerkschaftsbunds (CNG); dieser fusionierte per 1.1.2003 mit der VSA zu Travail.Suisse)", "Schweizerischer Arbeitgeberverband (bis 1996: Zentralverband Schweizerischer Arbeitgeber-Organisationen ZSAO)", "Vereinigung schweizerischer Angestelltenverbände", "Verband des Personals öffentlicher Dienste", "Verband öffentlicher Verkehr", "Touring Club Schweiz", "Verkehrs-Club der Schweiz", "Automobil Club der Schweiz", "Schweizer Bischofskonferenz", "Schweizerischer Städteverband", "Schweizerischer Gemeindeverband", "Konferenz der Kantonsregierungen", "Konferenz der kantonalen Justiz- und Polizeidirektoren", "Schweizerische Gesundheitsdirektorenkonferenz", "Konferenz der kantonalen Landwirtschaftsdirektoren"),stringsAsFactors =FALSE)# Parteikürzel in Grossbuchstaben parteinamen$kuerzel <-toupper(parteinamen$kuerzel)# Neue Spalte mit "p-" Präfix für späteren Lookup der Parteiparolenparteinamen$kuerzel_vote_parole <-paste0("p-", parteinamen$kuerzel) # Spaltenreihenfolge anpassen: p_kuerzel, kuerzel, nameparteinamen <- parteinamen[, c("kuerzel_vote_parole","kuerzel","name")]# Anzeige mit datatable()datatable(parteinamen,class ='nowrap',filter ='top',options =list(pageLength =7,scrollX =TRUE,search =list(regex =TRUE,caseInsensitive =TRUE)))
# Parolen Header extrahieren um Parteinamen für Lookup vorzubereitenvoting_parties <-paste(grep("^p-", names(voting_5y), value =TRUE), collapse =", ")voting_5y %>%select(anr, # Spalten-Wahl datum, titel_kurz_d, titel_off_d, rechtsform, #1 Obligatorisches Referendum#2 Fakultatives Referendum#3 Volksinitiative#4 Direkter Gegenentwurf zu einer Volksinitiative#5 Stichfrage dep,`br-pos`, #1 Befürwortend#2 Ablehnend#3 Keine#8 Vorzug für den Gegenentwurf (bei Stichfragen)#9 Vorzug für die Volksinitiative (bei Stichfragen)#. Missing legisjahr,`pa-iv`,`bv-pos`, #1 Befürwortend#2 Ablehnend#3 Keine Abstimmungsempfehlung des Parlaments#8 Vorzug für den Gegenentwurf (bei Stichfragen)`nr-pos`, #1 Befürwortende Mehrheit im Nationalrat#2 Ablehnende Mehrheit im Nationalrat#3 Keine Abstimmungsempfehlung des Nationalrats#8 Vorzug für den Gegenentwurf (bei Stichfragen) nrja, nrnein,`sr-pos`, #1 Befürwortende Mehrheit im Ständerat#2 Ablehnende Mehrheit im Ständerat#3 Keine Abstimmungsempfehlung des Ständerats#8 Vorzug für den Gegenentwurf (bei Stichfragen) srja, srnein,# Parteiparolenstarts_with("p-"),#1 Ja-Parole#2 Nein-Parole#3 keine Parole abzugeben#4 empfahl, einen leeren Stimmzettel einzulegen#5 Stimmfreigabe#8 Bevorzugung des Gegenentwurfs (bei Stichfrage)#9 Bevorzugung der Volksinitiative (bei Stichfrage)#66 Neutral: keine Parole oder Empfehlung auf leer einlegen #9999 Organisation existiert nicht#. Unbekannt# Parteiparolen Kanton / Parteisektionstarts_with("p-dev-"),#1 Ja-Parole#2 Nein-Parole#3 keine Parole abzugeben#4 empfahl, einen leeren Stimmzettel einzulegen#5 Stimmfreigabe#8 Bevorzugung des Gegenentwurfs (bei Stichfrage)#9 Bevorzugung der Volksinitiative (bei Stichfrage)# [leer] Parole gleich wie Mutterpartei (oder unbekannt) volk, #0 Eine Mehrheit der Abstimmenden hat die Vorlage abgelehnt#1 Eine Mehrheit der Abstimmenden hat die Vorlage angenommen#8 Bei Stichfragen: Mehrheit für Gegenentwurfs#9 Bei Stichfragen: Mehrheit Volksinitiative stand,#0 Die Vorlage hat keine Mehrheit der Standesstimmen er-reicht#1 Die Vorlage hat die Mehrheit der Standesstimmen erreicht#3 Ständemehr nicht notwendig#8 Bei Stichfragen: Mehrheit für Gegenentwurf#9 Bei Stichfragen: Mehrheit für Volksinitiative annahme, #0 Ablehnung der Vorlage#1 Annahme der Vorlage#8 Bei Stichfragen: Gegenentwurf angenommen#9 Bei Stichfragen: Volksinitiative angenommen#. Bei Stichfragen: Ergebnis der Stichfrage obsolet berecht, stimmen, bet, leer, ungultig, gultig, volkja, volknein,`volkja-proz`)
# TODO Die Kantonalen Abstimmungen finden nicht in allen kantonen gleichzeitg statt. Deshalb genauer die Räte/Konstellation zum Zeitpunkt der jeweiligen Abstimmung zu prüfen.# Struktur der "schön formatierten" Exceldatei lässt keinen "simplen" Import zu.# Header ist in Zeile 2 und nicht vollständig# Daten (für Kantone) starten in Zeile 4 aber enden auf Zeile 29 bevor es mit Kommentaren und Fussnoten weitergeht # Header aus Zeile 2 für Spaltennamen lesentmp_header <-read_excel("~/CAS/Zertifikatsarbeit/data/elections/je-d-17.02.05.01.03_KANTON_Kantonale_Parlamentswahlen.xlsx", sheet =1, skip =1, # Header ist Zeile 2n_max =0) %>%names()# Lücken im Header anpassen (i.e. erste beiden Spalten benennen)tmp_header <-c("Kanton", "Leer", tmp_header)tmp_name_map <-c("Kanton"="Kanton","Leer"="Leer","Wahljahr 5)"="Wahljahr","FDP 2)"="FDP","SP"="SP","SVP"="SVP","LPS 2)"="LPS","EVP"="EVP","CSP"="CSP","GLP"="GLP","Die Mitte 8)"="Mitte","CVP 3) 8)"="CVP","BDP 8)"="BDP","PdA"="PdA","PSA"="PSA","Grüne 9)"="Grüne","FGA"="FGA","Sol."="Sol.","EDU"="EDU","Lega"="Lega","MCG (MCR)"="MCR","Übrige 4)"="Übrige","Total"="Total")# Automatisch ersetzentmp_header <-ifelse(tmp_header %in%names(tmp_name_map), tmp_name_map[tmp_header], tmp_header)print(tmp_header)
# Daten ab Zeile 4 importierenelec_kantonsparlament_raw <-read_excel("~/CAS/Zertifikatsarbeit/data/elections/je-d-17.02.05.01.03_KANTON_Kantonale_Parlamentswahlen.xlsx", sheet =1, skip =3, # überspringt die ersten 3 Zeilencol_names = tmp_header)# Schritt 4: Nur Zeilen behalten, in denen "Wahljahr" nicht NA istelec_kantonsparlament <- elec_kantonsparlament_raw %>%filter(!is.na(Wahljahr)) %>%select(-Leer)# Ergebnis anzeigenprint(elec_kantonsparlament)
Die Kantonalen Abstimmungen finden nicht in allen kantonen gleichzeitg statt. Deshalb genauer die Räte/Konstellation zum Zeitpunkt der jeweiligen Abstimmung zu prüfen.
Die Struktur der “schön formatierten” Exceldatei lässt keinen “simplen” Import zu.
1 Excelsheet / Jahr
Header ist in Zeile 2 und nicht vollständig
Daten (für Kantone) starten in Zeile 4 aber enden auf Zeile 29 bevor es mit Kommentaren und Fussnoten weitergeht.
# Objekt erstellen, mit Sheets als tibble/dataframedaten_liste <-setNames(lapply(selected_sheets,function(sheet) import_election_data (dateipfad, sheet)), selected_sheets)str(daten_liste)
List of 6
$ 2024: tibble [494 × 4] (S3: tbl_df/tbl/data.frame)
..$ Kanton : chr [1:494] "Zürich" "Zürich" "Zürich" "Zürich" ...
..$ Wahljahr: num [1:494] 2023 2023 2023 2023 2023 ...
..$ Partei : chr [1:494] "FDP 2" "SP" "SVP" "LP 2" ...
..$ Wert : num [1:494] 1 1 2 NA 0 NA 0 1 NA NA ...
$ 2023: tibble [494 × 4] (S3: tbl_df/tbl/data.frame)
..$ Kanton : chr [1:494] "Zürich" "Zürich" "Zürich" "Zürich" ...
..$ Wahljahr: num [1:494] 2023 2023 2023 2023 2023 ...
..$ Partei : chr [1:494] "FDP 2)" "SP" "SVP" "LP 2)" ...
..$ Wert : num [1:494] 1 1 2 NA 0 NA 0 1 NA NA ...
$ 2022: tibble [494 × 4] (S3: tbl_df/tbl/data.frame)
..$ Kanton : chr [1:494] "Zürich" "Zürich" "Zürich" "Zürich" ...
..$ Wahljahr: num [1:494] 2019 2019 2019 2019 2019 ...
..$ Partei : chr [1:494] "FDP 2)" "SP" "SVP" "LP 2)" ...
..$ Wert : num [1:494] 1 1 2 NA 0 NA NA NA 1 0 ...
$ 2021: tibble [494 × 4] (S3: tbl_df/tbl/data.frame)
..$ Kanton : chr [1:494] "Zürich" "Zürich" "Zürich" "Zürich" ...
..$ Wahljahr: num [1:494] 2019 2019 2019 2019 2019 ...
..$ Partei : chr [1:494] "FDP 2)" "SP" "SVP" "LP 2)" ...
..$ Wert : num [1:494] 1 1 2 NA 0 NA NA NA 1 0 ...
$ 2020: tibble [780 × 4] (S3: tbl_df/tbl/data.frame)
..$ Kanton : chr [1:780] "Zürich" "Zürich" "Zürich" "Zürich" ...
..$ Wahljahr: num [1:780] 2019 2019 2019 2019 2019 ...
..$ Partei : chr [1:780] "FDP 2)" "CVP 3)" "SP" "SVP" ...
..$ Wert : num [1:780] 1 1 1 2 NA NA NA 0 NA NA ...
$ 2019: tibble [780 × 4] (S3: tbl_df/tbl/data.frame)
..$ Kanton : chr [1:780] "Zürich" "Zürich" "Zürich" "Zürich" ...
..$ Wahljahr: num [1:780] 2019 2019 2019 2019 2019 ...
..$ Partei : chr [1:780] "FDP 2)" "CVP 3)" "SP" "SVP" ...
..$ Wert : num [1:780] 1 1 2 2 NA NA NA 0 NA NA ...
Code anzeigen
lapply(daten_liste, summary)
$`2024`
Kanton Wahljahr Partei Wert
Length:494 Min. :2020 Length:494 Min. :0.000
Class :character 1st Qu.:2022 Class :character 1st Qu.:0.000
Mode :character Median :2023 Mode :character Median :1.000
Mean :2023 Mean :1.613
3rd Qu.:2024 3rd Qu.:2.000
Max. :2024 Max. :7.000
NA's :303
$`2023`
Kanton Wahljahr Partei Wert
Length:494 Min. :2020 Length:494 Min. :0.000
Class :character 1st Qu.:2020 Class :character 1st Qu.:0.000
Mode :character Median :2022 Mode :character Median :1.000
Mean :2022 Mean :1.647
3rd Qu.:2023 3rd Qu.:2.000
Max. :2023 Max. :7.000
NA's :307
$`2022`
Kanton Wahljahr Partei Wert
Length:494 Min. :2018 Length:494 Min. :0.000
Class :character 1st Qu.:2020 Class :character 1st Qu.:0.000
Mode :character Median :2020 Mode :character Median :1.000
Mean :2020 Mean :1.613
3rd Qu.:2022 3rd Qu.:2.000
Max. :2022 Max. :7.000
NA's :303
$`2021`
Kanton Wahljahr Partei Wert
Length:494 Min. :2017 Length:494 Min. :0.000
Class :character 1st Qu.:2018 Class :character 1st Qu.:0.000
Mode :character Median :2020 Mode :character Median :1.000
Mean :2019 Mean :1.613
3rd Qu.:2020 3rd Qu.:2.000
Max. :2021 Max. :7.000
NA's :303
$`2020`
Kanton Wahljahr Partei Wert
Length:780 Min. :2016 Length:780 Min. :0.000
Class :character 1st Qu.:2018 Class :character 1st Qu.:0.000
Mode :character Median :2019 Mode :character Median :1.000
Mean :2019 Mean :1.604
3rd Qu.:2020 3rd Qu.:2.000
Max. :2020 Max. :7.000
NA's :588
$`2019`
Kanton Wahljahr Partei Wert
Length:780 Min. :2015 Length:780 Min. :0.000
Class :character 1st Qu.:2016 Class :character 1st Qu.:0.000
Mode :character Median :2018 Mode :character Median :1.000
Mean :2017 Mean :1.596
3rd Qu.:2018 3rd Qu.:2.000
Max. :2019 Max. :7.000
NA's :587
Code anzeigen
# Alle tibbles zu einem Dataframe zusammenfügenelec_kantonale_regierung_combined <-bind_rows(daten_liste,.id ="Sheet")datatable(elec_kantonale_regierung_combined,class ='nowrap',filter ='top',options =list(pageLength =7,scrollX =TRUE,search =list(regex =TRUE,caseInsensitive =TRUE)))
Code anzeigen
# TODO:# Parteinamen bereinigen!# finales file: elec_kantonale_regierung_final# Dataframe als Excel schreiben# write_xlsx(elec_kantonale_regierung_final,# "elec_kantonale_regierung_final.xlsx")
3.3.3 Gemeindeebene
3.3.3.1 Exekutiven der statistischen Städte
1 Excelsheet / Jahr
Header zweizeilig mit Start in Zeile –> 3 skip = 2, n_max = 2,
# Objekt erstellen, mit Sheets als tibble/dataframedaten_liste <-setNames(lapply(selected_sheets,function(sheet) importiere_sheet(dateipfad, sheet)), selected_sheets)str(daten_liste)
List of 6
$ 2024: tibble [7,515 × 10] (S3: tbl_df/tbl/data.frame)
..$ Kantons-Nr. : chr [1:7515] "1" "1" "1" "1" ...
..$ Kanton : chr [1:7515] "ZH" "ZH" "ZH" "ZH" ...
..$ Gemeinde-Nr. : num [1:7515] 230 230 230 230 230 230 230 230 230 230 ...
..$ Gemeinde : chr [1:7515] "Winterthur" "Winterthur" "Winterthur" "Winterthur" ...
..$ Wahljahr : num [1:7515] 2022 2022 2022 2022 2022 ...
..$ Einwohner : num [1:7515] 115129 115129 115129 115129 115129 ...
..$ Gemeindegrösse_Cluster: chr [1:7515] "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" ...
..$ Partei : chr [1:7515] "FDP 1" "FDP 1" "FDP 1" "Die Mitte 2" ...
..$ m_w_Total : chr [1:7515] "Frauen" "Männer" "Total" "Frauen" ...
..$ Wert : num [1:7515] 0 1 1 0 1 1 NA NA NA 1 ...
$ 2023: tibble [7,776 × 10] (S3: tbl_df/tbl/data.frame)
..$ Kantons-Nr. : chr [1:7776] "1" "1" "1" "1" ...
..$ Kanton : chr [1:7776] "ZH" "ZH" "ZH" "ZH" ...
..$ Gemeinde-Nr. : num [1:7776] 230 230 230 230 230 230 230 230 230 230 ...
..$ Gemeinde : chr [1:7776] "Winterthur" "Winterthur" "Winterthur" "Winterthur" ...
..$ Wahljahr : num [1:7776] 2022 2022 2022 2022 2022 ...
..$ Einwohner : num [1:7776] 115129 115129 115129 115129 115129 ...
..$ Gemeindegrösse_Cluster: chr [1:7776] "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" ...
..$ Partei : chr [1:7776] "FDP 1" "FDP 1" "FDP 1" "Die Mitte 2" ...
..$ m_w_Total : chr [1:7776] "Frauen" "Männer" "Total" "Frauen" ...
..$ Wert : num [1:7776] 0 1 1 0 1 1 NA NA NA 1 ...
$ 2022: tibble [7,776 × 10] (S3: tbl_df/tbl/data.frame)
..$ Kantons-Nr. : chr [1:7776] "1" "1" "1" "1" ...
..$ Kanton : chr [1:7776] "ZH" "ZH" "ZH" "ZH" ...
..$ Gemeinde-Nr. : num [1:7776] 230 230 230 230 230 230 230 230 230 230 ...
..$ Gemeinde : chr [1:7776] "Winterthur" "Winterthur" "Winterthur" "Winterthur" ...
..$ Wahljahr : num [1:7776] 2022 2022 2022 2022 2022 ...
..$ Einwohner : num [1:7776] 115129 115129 115129 115129 115129 ...
..$ Gemeindegrösse_Cluster: chr [1:7776] "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" ...
..$ Partei : chr [1:7776] "FDP 1" "FDP 1" "FDP 1" "Die Mitte 2" ...
..$ m_w_Total : chr [1:7776] "Frauen" "Männer" "Total" "Frauen" ...
..$ Wert : num [1:7776] 0 1 1 0 1 1 NA NA NA 1 ...
$ 2021: tibble [7,776 × 10] (S3: tbl_df/tbl/data.frame)
..$ Kantons-Nr. : chr [1:7776] "1" "1" "1" "1" ...
..$ Kanton : chr [1:7776] "ZH" "ZH" "ZH" "ZH" ...
..$ Gemeinde-Nr. : num [1:7776] 230 230 230 230 230 230 230 230 230 230 ...
..$ Gemeinde : chr [1:7776] "Winterthur" "Winterthur" "Winterthur" "Winterthur" ...
..$ Wahljahr : num [1:7776] 2018 2018 2018 2018 2018 ...
..$ Einwohner : num [1:7776] 110912 110912 110912 110912 110912 ...
..$ Gemeindegrösse_Cluster: chr [1:7776] "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" ...
..$ Partei : chr [1:7776] "FDP 1" "FDP 1" "FDP 1" "Die Mitte 2" ...
..$ m_w_Total : chr [1:7776] "Frauen" "Männer" "Total" "Frauen" ...
..$ Wert : num [1:7776] 1 1 2 NA NA NA 0 1 1 2 ...
$ 2020: tibble [7,290 × 10] (S3: tbl_df/tbl/data.frame)
..$ Kantons-Nr. : chr [1:7290] "1" "1" "1" "1" ...
..$ Kanton : chr [1:7290] "ZH" "ZH" "ZH" "ZH" ...
..$ Gemeinde-Nr. : num [1:7290] 230 230 230 230 230 230 230 230 230 230 ...
..$ Gemeinde : chr [1:7290] "Winterthur" "Winterthur" "Winterthur" "Winterthur" ...
..$ Wahljahr : num [1:7290] 2018 2018 2018 2018 2018 ...
..$ Einwohner : num [1:7290] 110912 110912 110912 110912 110912 ...
..$ Gemeindegrösse_Cluster: chr [1:7290] "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" ...
..$ Partei : chr [1:7290] "FDP 1)" "FDP 1)" "FDP 1)" "CVP" ...
..$ m_w_Total : chr [1:7290] "Frauen" "Männer" "Total" "Frauen" ...
..$ Wert : num [1:7290] 1 1 2 0 1 1 2 1 3 NA ...
$ 2019: tibble [14,580 × 11] (S3: tbl_df/tbl/data.frame)
..$ Kantons-Nr. : chr [1:14580] "1" "1" "1" "1" ...
..$ Kanton : chr [1:14580] "ZH" "ZH" "ZH" "ZH" ...
..$ Gemeinde-Nr. : num [1:14580] 230 230 230 230 230 230 230 230 230 230 ...
..$ Gemeinde : chr [1:14580] "Winterthur" "Winterthur" "Winterthur" "Winterthur" ...
..$ Einwohner : num [1:14580] 111851 111851 111851 111851 111851 ...
..$ Grössenklasse-Nr. : chr [1:14580] "4" "4" "4" "4" ...
..$ Grössenklasse : chr [1:14580] "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" ...
..$ Gemeindegrösse_Cluster: chr [1:14580] "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" "≥ 100'000 Einwohnerinnen und Einwohner" ...
..$ Partei : chr [1:14580] "FDP 1)" "FDP 1)" "FDP 1)" "CVP" ...
..$ m_w_Total : chr [1:14580] "Frauen" "Männer" "Total" "Frauen" ...
..$ Wert : num [1:14580] 1 1 2 0 1 1 2 1 3 NA ...
Code anzeigen
lapply(daten_liste, summary)
$`2024`
Kantons-Nr. Kanton Gemeinde-Nr. Gemeinde
Length:7515 Length:7515 Min. : 2 Length:7515
Class :character Class :character 1st Qu.: 581 Class :character
Mode :character Mode :character Median :2769 Mode :character
Mean :2936
3rd Qu.:5113
Max. :6711
Wahljahr Einwohner Gemeindegrösse_Cluster Partei
Min. :2020 Min. : 4957 Length:7515 Length:7515
1st Qu.:2021 1st Qu.: 11680 Class :character Class :character
Median :2022 Median : 15763 Mode :character Mode :character
Mean :2022 Mean : 25286
3rd Qu.:2024 3rd Qu.: 22110
Max. :2024 Max. :423193
m_w_Total Wert
Length:7515 Min. : 0.00
Class :character 1st Qu.: 1.00
Mode :character Median : 1.00
Mean : 1.73
3rd Qu.: 2.00
Max. :30.00
NA's :4986
$`2023`
Kantons-Nr. Kanton Gemeinde-Nr. Gemeinde
Length:7776 Length:7776 Min. : 2 Length:7776
Class :character Class :character 1st Qu.: 546 Class :character
Mode :character Mode :character Median :2770 Mode :character
Mean :2952
3rd Qu.:5192
Max. :6711
Wahljahr Einwohner Gemeindegrösse_Cluster Partei
Min. :2020 Min. : 4957 Length:7776 Length:7776
1st Qu.:2020 1st Qu.: 12104 Class :character Class :character
Median :2021 Median : 15754 Mode :character Mode :character
Mean :2021 Mean : 25369
3rd Qu.:2022 3rd Qu.: 22193
Max. :2023 Max. :423193
m_w_Total Wert
Length:7776 Min. : 0.000
Class :character 1st Qu.: 1.000
Mode :character Median : 1.000
Mean : 1.719
3rd Qu.: 2.000
Max. :30.000
NA's :5316
$`2022`
Kantons-Nr. Kanton Gemeinde-Nr. Gemeinde
Length:7776 Length:7776 Min. : 2 Length:7776
Class :character Class :character 1st Qu.: 546 Class :character
Mode :character Mode :character Median :2770 Mode :character
Mean :2952
3rd Qu.:5192
Max. :6711
Wahljahr Einwohner Gemeindegrösse_Cluster Partei
Min. :2019 Min. : 4957 Length:7776 Length:7776
1st Qu.:2020 1st Qu.: 12104 Class :character Class :character
Median :2021 Median : 15754 Mode :character Mode :character
Mean :2021 Mean : 25353
3rd Qu.:2022 3rd Qu.: 22193
Max. :2022 Max. :423193
m_w_Total Wert
Length:7776 Min. : 0.000
Class :character 1st Qu.: 1.000
Mode :character Median : 1.000
Mean : 1.725
3rd Qu.: 2.000
Max. :30.000
NA's :5325
$`2021`
Kantons-Nr. Kanton Gemeinde-Nr. Gemeinde
Length:7776 Length:7776 Min. : 2 Length:7776
Class :character Class :character 1st Qu.: 546 Class :character
Mode :character Mode :character Median :2770 Mode :character
Mean :2952
3rd Qu.:5192
Max. :6711
Wahljahr Einwohner Gemeindegrösse_Cluster Partei
Min. :2017 Min. : 4994 Length:7776 Length:7776
1st Qu.:2018 1st Qu.: 12068 Class :character Class :character
Median :2020 Median : 15754 Mode :character Mode :character
Mean :2020 Mean : 25043
3rd Qu.:2021 3rd Qu.: 21718
Max. :2021 Max. :409241
m_w_Total Wert
Length:7776 Min. : 0.000
Class :character 1st Qu.: 1.000
Mode :character Median : 1.000
Mean : 1.722
3rd Qu.: 2.000
Max. :30.000
NA's :5316
$`2020`
Kantons-Nr. Kanton Gemeinde-Nr. Gemeinde
Length:7290 Length:7290 Min. : 2 Length:7290
Class :character Class :character 1st Qu.: 546 Class :character
Mode :character Mode :character Median :2770 Mode :character
Mean :2951
3rd Qu.:5192
Max. :6711
Wahljahr Einwohner Gemeindegrösse_Cluster Partei
Min. :2016 Min. : 4994 Length:7290 Length:7290
1st Qu.:2017 1st Qu.: 11572 Class :character Class :character
Median :2018 Median : 15710 Mode :character Mode :character
Mean :2018 Mean : 24871
3rd Qu.:2020 3rd Qu.: 21090
Max. :2020 Max. :409241
m_w_Total Wert
Length:7290 Min. : 0.000
Class :character 1st Qu.: 1.000
Mode :character Median : 1.000
Mean : 1.717
3rd Qu.: 2.000
Max. :30.000
NA's :4827
$`2019`
Kantons-Nr. Kanton Gemeinde-Nr. Gemeinde
Length:14580 Length:14580 Min. : 2 Length:14580
Class :character Class :character 1st Qu.: 546 Class :character
Mode :character Mode :character Median :2770 Mode :character
Mean :2951
3rd Qu.:5192
Max. :6711
Einwohner Grössenklasse-Nr. Grössenklasse Gemeindegrösse_Cluster
Min. : 4928 Length:14580 Length:14580 Length:14580
1st Qu.: 11733 Class :character Class :character Class :character
Median : 15693 Mode :character Mode :character Mode :character
Mean : 25006
3rd Qu.: 21506
Max. :415367
Partei m_w_Total Wert
Length:14580 Length:14580 Min. : 0.00
Class :character Class :character 1st Qu.: 0.00
Mode :character Mode :character Median : 0.00
Mean : 0.65
3rd Qu.: 1.00
Max. :30.00
NA's :8084
Code anzeigen
# Alle tibbles zu einem Dataframe zusammenfügenelec_gemeinde_exekutiven_combined <-bind_rows(daten_liste,.id ="Sheet") %>%select(-c('Grössenklasse-Nr.', Grössenklasse))datatable(elec_gemeinde_exekutiven_combined,class ='nowrap',filter ='top',options =list(pageLength =7,scrollX =TRUE,search =list(regex =TRUE,caseInsensitive =TRUE)))
Code anzeigen
# TODO:# Parteinamen bereinigen!# finales file: elec_gemeinde_exekutiven_final# Dataframe als Excel schreiben# write_xlsx(elec_gemeinde_exekutiven_final,# "elec_gemeinde_exekutiven_final.xlsx")
# Sitze pro Kanton, Partei und Jahr # long format df_sum <- elec_nationalrat_reduced %>%group_by(CantonAbbreviation, PartyAbbreviation) %>%summarise(sum_value =sum(value, na.rm =TRUE),.groups ="drop")# wide format# Pivotieren: Partei-Spalten erzeugen df_wide <- df_sum %>%pivot_wider(names_from = PartyAbbreviation,values_from = sum_value,values_fill =0)# Partei-Spaltennamen extrahieren (ohne Kanton/Jahr) partei_cols <-setdiff(names(df_wide),c("CantonAbbreviation"))# Spaltensummen der Parteien berechnen für Sortierung partei_sums <-colSums(df_wide[partei_cols])# Zeilensumme der Kantone/Jahre hinzufügen df_wide$Total <-rowSums(df_wide[partei_cols])# Parteispalten-Anordnung nach Summe sortieren sorted_partei <-names(sort(partei_sums,decreasing =TRUE))# Dataframe neu anordnen: Kanton/Jahr, sortierte und gefilterte Parteien elec_nationalrat_final <- df_wide[, c(setdiff(names(df_wide), partei_cols), sorted_partei)] %>%arrange(desc(Total))datatable(elec_nationalrat_final,class ='nowrap',filter ='top',options =list(pageLength =7,scrollX =TRUE,search =list(regex =TRUE,caseInsensitive =TRUE)))
4.2.1.2 Ständerat
Code anzeigen
############################################################################################### BACKUP 04.06.2025 #######################################################################################################TODO Es kann innerhalb der Legislatur Wechsel geben --> Anstelle der heute "Aktiven" ist es deshalb genauer die Räte/Konstellation zum Zeitpunkt der jeweiligen Abstimmung zu prüfen.# Anzeige mit datatable()datatable(elec_ständerat,class ='nowrap',filter ='top',options =list(pageLength =7,scrollX =TRUE,search =list(regex =TRUE,caseInsensitive =TRUE)))
Code anzeigen
# Fehlende Werte (NA), Klassen und Levels prüfenAbstract(elec_ständerat)
# Sitze pro Kanton, Partei und Jahr # long format df_sum <- elec_ständerat_reduced %>%group_by(CantonAbbreviation, PartyAbbreviation) %>%summarise(sum_value =sum(value, na.rm =TRUE),.groups ="drop")# wide format# Pivotieren: Partei-Spalten erzeugen df_wide <- df_sum %>%pivot_wider(names_from = PartyAbbreviation,values_from = sum_value,values_fill =0)# Partei-Spaltennamen extrahieren (ohne Kanton/Jahr) partei_cols <-setdiff(names(df_wide),c("CantonAbbreviation"))# Spaltensummen der Parteien berechnen für Sortierung partei_sums <-colSums(df_wide[partei_cols])# Zeilensumme der Kantone/Jahre hinzufügen df_wide$Total <-rowSums(df_wide[partei_cols])# Parteispalten-Anordnung nach Summe sortieren sorted_partei <-names(sort(partei_sums,decreasing =TRUE))# Dataframe neu anordnen: Kanton/Jahr, sortierte und gefilterte Parteien elec_ständerat_final <- df_wide[, c(setdiff(names(df_wide), partei_cols), sorted_partei)] %>%arrange(desc(Total))datatable(elec_ständerat_final,class ='nowrap',filter ='top',options =list(pageLength =7,scrollX =TRUE,search =list(regex =TRUE,caseInsensitive =TRUE)))
4.2.2 Kantonsebene
4.2.2.1 Kantonsregierung
Code anzeigen
############################################################################################### BACKUP 03.06.2025 ####################################################################################################### # datatable(elec_kantonale_regierung_final,# class = 'nowrap',# filter = 'top',# options = list(pageLength = 7,# scrollX = TRUE,# search = list(regex = TRUE,# caseInsensitive = TRUE)))# # # Änderungen verfolgen# # Partei-Spalten bestimmen# parteien <- setdiff(names(elec_kantonsregierung_final), c("Kanton", "Wahljahr", "Total"))# # # Dataframe nach Kanton und Wahljahr sortieren und ins lange Format bringen# df_long <- elec_kantonsregierung_final %>%# arrange(Kanton, Wahljahr) %>%# pivot_longer(# cols = all_of(parteien),# names_to = "Partei",# values_to = "Wert_neu"# ) %>%# group_by(Kanton, Partei) %>%# arrange(Wahljahr, .by_group = TRUE) %>%# mutate(Wert_alt = lag(Wert_neu)) %>%# ungroup()# # # Änderungen filtern: Zeige nur, wo sich der Wert geändert hat (und nicht NA)# elec_kantonsregierung_changelog <- df_long %>%# filter(!is.na(Wert_alt),# Wert_neu != Wert_alt) %>%# select(Kanton,# Wahljahr,# Partei,# Wert_alt,# Wert_neu)# # # datatable(elec_kantonsregierung_changelog,# class = 'nowrap',# filter = 'top',# options = list(pageLength = 7,# scrollX = TRUE,# search = list(regex = TRUE,# caseInsensitive = TRUE)))
4.3 Parteilandschaft
4.3.1 Multi-Dimensions-Model
4.3.1.1 Minimalwerte
Für jede Partei den Minimalwert des Abstimmungsverhaltens zu verwenden, basiert auf der Zielsetzung, die klarste politische Position einer Partei in einem bestimmten Themenbereich zu identifizieren. Diese Methodik stellt sicher, dass auch bei wenigen Abweichungen von der Mehrheitslinie die tatsächliche Haltung der Partei deutlich erkennbar bleibt.
4.3.1.4 Hauptparteien: Durchschnittswerte als Zentrum und Min/Max als Ellipse / Verbände sowie Klein- und Regionalparteien nur mit ihrem Durchschnittswert